/*
 * Copyright (c) 2022 Hong Jiahua
 * https://gitee.com/arrco/jh_XOR_list
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include <stdio.h>
#include <stdlib.h>

#include "jh_XOR_list.h"
/************************************************************************/
/*                                                                      */
/************************************************************************/

/************************************************************************/
/*                                                                      */
/************************************************************************/

//遍历链表示例
void xor_list_for_each_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    printf("********************************\n");
    printf("遍历链表 方式一\n");
    printf("********************************\n");
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表 方式二\n");
    printf("********************************\n");
    JH_XOR_LIST_FOR_EACH_SAFE(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表 方式三\n");
    printf("********************************\n");
    my_test_t* val3;
    JH_XOR_LIST_FOR_EACH_ENTRY(val3, &myhead, list) {
        printf("%d, ", val3->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表 方式四\n");
    printf("********************************\n");
    my_test_t* val4;
    JH_XOR_LIST_FOR_EACH_ENTRY_SAFE(val4, &myhead, list) {
        printf("%d, ", val4->data);
    }
    printf("\n");
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//反向遍历链表示例
void xor_list_for_each_reverse_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    printf("********************************\n");
    printf("反向遍历链表 方式一\n");
    printf("********************************\n");
    JH_XOR_LIST_FOR_EACH_REVERSE(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("反向遍历链表 方式二\n");
    printf("********************************\n");
    JH_XOR_LIST_FOR_EACH_SAFE_REVERSE(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("反向遍历链表 方式三\n");
    printf("********************************\n");
    my_test_t* val3;
    JH_XOR_LIST_FOR_EACH_ENTRY_REVERSE(val3, &myhead, list) {
        printf("%d, ", val3->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("反向遍历链表 方式四\n");
    printf("********************************\n");
    my_test_t* val4;
    JH_XOR_LIST_FOR_EACH_ENTRY_SAFE_REVERSE(val4, &myhead, list) {
        printf("%d, ", val4->data);
    }
    printf("\n");
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//链表添加数据与删除数据示例
//往链表尾添加与删除数据
void xor_list_add_and_delete_tail_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //往链表尾添加数据
    printf("********************************\n");
    printf("链表尾添加数据\n");
    printf("********************************\n");
    my_test_t* addval = malloc(sizeof(my_test_t));
    addval->data = 66;
    jh_xor_list_tail_insert(&myhead, &(addval->list));
    
    //遍历链表数据查看添加数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //往链表尾删除数据
    printf("********************************\n");
    printf("链表尾删除数据\n");
    printf("********************************\n");
    jh_xor_list_t* removenode = jha_xor_list_remove_tail(&myhead);
    my_test_t* removeval = JH_XOR_LIST_ENTRY(removenode, my_test_t, list);
    free(removeval);
    
    //遍历链表数据查看删除数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//往链表头添加与删除数据
void xor_list_add_and_delete_head_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_head_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //往链表头添加数据
    printf("********************************\n");
    printf("链表头添加数据\n");
    printf("********************************\n");
    my_test_t* addval = malloc(sizeof(my_test_t));
    addval->data = 66;
    jh_xor_list_head_insert(&myhead, &(addval->list));
    
    //遍历链表数据查看添加数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //往链表头删除数据
    printf("********************************\n");
    printf("链表头删除数据\n");
    printf("********************************\n");
    jh_xor_list_t* removenode = jha_xor_list_remove_head(&myhead);
    my_test_t* removeval = JH_XOR_LIST_ENTRY(removenode, my_test_t, list);
    free(removeval);
    
    //遍历链表数据查看删除数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_head(&myhead);
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//查看链表头和尾的数据
void xor_list_peek_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //查看链表头的数据
    printf("********************************\n");
    printf("查看链表头的数据\n");
    printf("********************************\n");
    my_test_t* headval = JH_XOR_LIST_PEEK_HEAD_TYPE(&myhead, my_test_t, list);
    printf("%d\n", headval->data);
    
    //查看链表尾的数据
    printf("********************************\n");
    printf("查看链表尾的数据\n");
    printf("********************************\n");
    my_test_t* tailval = JH_XOR_LIST_PEEK_TAIL_TYPE(&myhead, my_test_t, list);
    printf("%d\n", tailval->data);
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//遍历链表中删除特定数据
void xor_list_for_each_delete_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表中删除数据 方式一\n");
    printf("********************************\n");
    //删除大于7的数据
    JH_XOR_LIST_FOR_EACH_SAFE(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
        if(val->data > 5) {
            JH_XOR_LIST_DEL_NODE(itemval, &myhead);
            free(val);
        }
    }
    printf("\n");
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表中删除数据 方式二\n");
    printf("********************************\n");
    //删除小于3的数据
    my_test_t* delval;
    JH_XOR_LIST_FOR_EACH_ENTRY_SAFE(delval, &myhead, list) {
        printf("%d, ", delval->data);
        if(delval->data < 3) {
            JH_XOR_LIST_DEL_NODE(&(delval->list), &myhead);
            free(delval);
        }
    }
    printf("\n");
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        if(tmp == NULL)
            break;
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//遍历链表中添加特定数据
void xor_list_for_each_add_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表中添加数据 方式一\n");
    printf("********************************\n");
    //在2后面添加数据
    JH_XOR_LIST_FOR_EACH_SAFE(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
        if(val->data == 2) {
            my_test_t* addval = malloc(sizeof(my_test_t));
            addval->data = 66;
            JH_XOR_LIST_ADD_NODE(itemval, &myhead, &(addval->list));
        }
    }
    printf("\n");
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表中添加数据 方式二\n");
    printf("********************************\n");
    //在8后面添加数据
    my_test_t* findval;
    JH_XOR_LIST_FOR_EACH_ENTRY_SAFE(findval, &myhead, list) {
        printf("%d, ", findval->data);
        if(findval->data == 8) {
            my_test_t* addval = malloc(sizeof(my_test_t));
            addval->data = 99;
            JH_XOR_LIST_ADD_NODE(&(findval->list), &myhead, &(addval->list));
        }
    }
    printf("\n");
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //删除并释放所有数据
    for(int i = 0; i < 12; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        if(tmp == NULL)
            break;
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//获取链表头和尾的数据并删除链表头和尾数据
void xor_list_delete_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("获取并删除链表头\n");
    printf("********************************\n");
    my_test_t* delval = JH_XOR_LIST_REMOVE_HEAD_TYPE(&myhead, my_test_t, list);
    printf("remove head %d\n", delval->data);
    free(delval);
    
    printf("********************************\n");
    printf("获取并删除链表尾\n");
    printf("********************************\n");
    delval = JH_XOR_LIST_REMOVE_TAIL_TYPE(&myhead, my_test_t, list);
    printf("remove tail %d\n", delval->data);
    free(delval);
    
    //遍历链表数据
    JH_XOR_LIST_FOR_EACH(itemval, &myhead) {
        my_test_t* val = JH_XOR_LIST_ENTRY(itemval, my_test_t, list);
        printf("%d, ", val->data);
    }
    printf("\n");
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        if(tmp == NULL)
            break;
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
}

//判断链表是否为空
void xor_list_is_empty_test(void)
{
    //定义用户的数据类型，同时将链表的数据结构放入结构体当中
    typedef struct {
        int data;
        jh_xor_list_t list;
    } my_test_t;

    //定义并初始化链表头
    JH_XOR_LIST_HEAD(myhead);
    
    printf("********************************\n");
    printf("判断链表是否为空\n");
    printf("********************************\n");
    printf("%d\n", jh_xor_list_is_empty(&myhead));
    
    //将10个数据放入链表中
    for(int i = 0; i < 10; i++) {
        my_test_t* val = malloc(sizeof(my_test_t));
        val->data = i;
        jh_xor_list_tail_insert(&myhead, &(val->list));
    }
    
    printf("%d\n", jh_xor_list_is_empty(&myhead));
    
    //删除并释放所有数据
    for(int i = 0; i < 10; i++) {
        jh_xor_list_t* tmp = jha_xor_list_remove_tail(&myhead);
        if(tmp == NULL)
            break;
        my_test_t* val = JH_XOR_LIST_ENTRY(tmp, my_test_t, list);
        free(val);
    }
    
    printf("%d\n", jh_xor_list_is_empty(&myhead));
}


int main(int argc, char* argv[])
{
    //遍历链表
    xor_list_for_each_test();
    
    //反向遍历链表
    xor_list_for_each_reverse_test();
    
    //往链表尾添加与删除数据
    xor_list_add_and_delete_tail_test();
    
    //往链表头添加与删除数据
    xor_list_add_and_delete_head_test();
    
    //查看链表头和尾的数据
    xor_list_peek_test();
    
    //遍历链表中删除特定数据
    xor_list_for_each_delete_test();
    
    //遍历链表中添加特定数据
    xor_list_for_each_add_test();
    
    //获取链表头和尾的数据并删除链表头和尾数据
    xor_list_delete_test();
    
    //判断链表是否为空
    xor_list_is_empty_test();
    
    return 0;
}